﻿package org.hive.managers.plugin
{
	import flash.events.Event;
	import flash.utils.Dictionary;
	
	import org.hive.Hive;
	import org.hive.data.*;
	import org.hive.display.LoaderData;
	import org.hive.display.utils.LoaderSet;
	import org.hive.events.LoaderEvent;
	import org.hive.managers.Manager;
	import org.hive.sequence.Sequence;

	
	public final class LoadManager extends Manager
	{  
		public function LoadManager( hive:Hive )
		{
		    super(hive);
		}

		/**
		 * 
		 * @param hive
		 * @return 
		 * 
		 */		
		public static function init(hive:Hive):LoadManager
        {
            if(Hive.DEBUG_MODE){trace( "LoadManager :: init" )}

            var manager:LoadManager = new LoadManager(hive);
            hive.registerManager(manager);
            
            //_____________ Register Object :: LoaderData
            function loaderDataFunc( action:*, sequence:Sequence, positionInSequence:int ):void {
                var ldr:LoaderData = action as LoaderData;
                manager.add( ldr );
                ldr.load(null);
            }
            hive.sequenceManager.registerAction(LoaderData, loaderDataFunc);
            
            //_____________ Register Object :: LoaderSet
            function loaderSetFunc( action:*, sequence:Sequence, positionInSequence:int ):void {
                var lds:LoaderSet = action as LoaderSet;
				manager.queueSet(lds);
            }
            hive.sequenceManager.registerAction(LoaderSet, loaderSetFunc);
            
            return manager;
        }
        
		private var queue:Array = [];
		
		public function queueSet( loaderSet:LoaderSet ):void
		{
			if(loaderSet != null){
				queue.push(loaderSet);
				if(queue.length == 1)
					loadSet(loaderSet);
			}
		}
		
		public function loadSet( loaderSet:LoaderSet ):void {
			loaderSet.addEventListener(LoaderEvent.ADDED, distributeLoaderElement);
			loaderSet.addEventListener(Event.COMPLETE, handleSetLoaded);
			loaderSet.startLoad();
		}
		
		private function handleSetLoaded(e:Event):void {
			var loaderSet = e.currentTarget;
			loaderSet.removeEventListener(LoaderEvent.ADDED, distributeLoaderElement);
			loaderSet.removeEventListener(Event.COMPLETE, handleSetLoaded);
			
			
			queue.shift();
			if(queue.length > 0){
				//trace(queue);
				loadSet(queue[0]);
			}
		}
		
		public function flushQueue():void {
			if(queue.length > 0){
				for(var i:int=0; i<queue.length; i++){
					queue[i].removeEventListener(LoaderEvent.ADDED, distributeLoaderElement);
					queue[i].removeEventListener(Event.COMPLETE, handleSetLoaded);
					
				}
				
				//var current:LoaderSet = queue[0];
				queue = new Array();
			}
		}
		
		public function isQueued(ls:LoaderSet):Boolean {
			if(queue.indexOf(ls) != -1) return true;
			return false;
		}
		
		private var maxLoading:int = 1;
		
		 /**
        *
        */
        private var LOADERSETS          :Array = new Array( );
        private var LOADERSETS_BY_NAME  :Dictionary = new Dictionary( true );
        
        private var LOADERS             :Array = new Array( );
        private var LOADERS_BY_NAME     :Dictionary = new Dictionary( true );
        private var LOADERS_BY_CONTENT  :Dictionary = new Dictionary( true );
        
		protected var loaderElementLib	:Dictionary = new Dictionary(false);
		
		/**
        *
        * @param	definition		Registers the class definition to the loader library.
        * @param	callback		Registers the callback function with the class definition: callback( loaderElement:* ).
        */
		
		public function registerLoaderElement( definition:Class, callback:Function )
		{
			loaderElementLib[ definition ] = callback;
		}
		
		private function distributeLoaderElement( e:LoaderEvent ):void
		{
			for ( var conditionalClass:* in loaderElementLib ) {
				if ( e.loader is conditionalClass ) {
					loaderElementLib[ conditionalClass ]( e.loader );
				}
			}
		}
				
		/**
		 * 
		 * @return 
		 * 
		 */		
		public function get loaders():Array
		{
		    return LOADERS;
		}
		
		/**
		 * 
		 * @return 
		 * 
		 */		
		public function get loaderSets():Array
		{
		    return LOADERSETS;
		}
		
		/**
		 * 
		 * @param loaderSet
		 * 
		 */		
		public function addLoaderSet( loaderSet:LoaderSet ):void
		{
			LOADERSETS_BY_NAME[ loaderSet.name ] = loaderSet;
			LOADERSETS.push( loaderSet );
		}
		
		/**
		 * 
		 * @param args
		 * 
		 */		
		public function add( ...args ):void
		{
			for (var i:int = 0; i < args.length; i++) {
				if( args[i] is LoaderData ){
					LOADERS_BY_CONTENT[ args[i].contentLoaderInfo ] = args[i];
				}
				else if( args[i] ){
					LOADERS_BY_CONTENT[ args[i] ] = args[i];
				}
				LOADERS_BY_NAME[ args[i].name ] = args[i];
				LOADERS.push( args[i] );
		    }
		}
		
        /**
         * 
         * @param names
         * 
         */		
        public function removeLoaderSetByName( ...names ):void
        {
            for (var i:Number = 0; i < names.length; i++)
            removeLoaderSet( getLoadersetByName( names[i] ) );
        }
		
		/**
		 * 
		 * @param loaderSet
		 * 
		 */		
		public function removeLoaderSet( loaderSet:LoaderSet ):void
		{
		    var i:uint = LOADERSETS.indexOf(loaderSet);
            if( i != -1 ){ 
                delete LOADERSETS[i];
            }
            delete LOADERSETS_BY_NAME[ loaderSet.name ];
		}
		
		/**
		 * 
		 * @param ldr
		 * 
		 */		
		public function removeLoader( ldr:* ):void
		{
		    var i:uint = LOADERS.indexOf(ldr);
		    if( i != -1 ) delete LOADERS[i];
			delete LOADERS_BY_NAME[ ldr.name ];
			if( ldr is LoaderData ) delete LOADERS_BY_CONTENT[ ldr.contentLoaderInfo ];
			/* else if( ldr is SoundData ) delete LOADERS_BY_CONTENT[ ldr ];
			else if( ldr is URLData ) delete LOADERS_BY_CONTENT[ ldr.data ]; */
		}
		
		/**
		 * 
		 * @param names
		 * 
		 */		
		public function removeLoaderByName( ...names ):void
		{
			for (var i:Number = 0; i < names.length; i++)
		    removeLoader( getLoaderByName( names[i] ) );
		}
		
		/**
		 * 
		 * @param name
		 * @return 
		 * 
		 */		
		public function getLoaderByName( name:String ):*
		{
			return LOADERS_BY_NAME[ name ];
		}
		
		/**
		 * 
		 * @param info
		 * @return 
		 * 
		 */		
		public function getLoaderByContent( info:* ):*
		{
			return LOADERS_BY_CONTENT[ info ];
		}
		
		/**
		 * 
		 * @param name
		 * @return 
		 * 
		 */		
		public function getLoadersetByName( name:String ):*
		{
			return LOADERSETS_BY_NAME[ name ];
		}
			
		
		
		
	}
}